Using delayed input texture evaluation¶
The intrinsics _evaluateDelayed()
and _evaluateDelayedP()
cause an input texture to evaluated only when the control has reached the intrinsic in the current shader.
This is different from what OSL normally does, which is evaluating any shaders on the input first, before starting this shader.
Selective execution¶
Consider a simple use case: a texture shader which randomly picks one of four input textures for each UV tile.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | shader Texture( color col1 = color(1, 0, 0), color col2 = color(0, 1, 0), color col3 = color(0, 0, 1), color col4 = color(1, 1, 1), output color c = 0) { int index = (int) floor(4 * noise("cell", u, v)); // random index if (index == 0) { c = col1; } if (index == 1) { c = col2; } if (index == 2) { c = col3; } if (index == 3) { c = col4; } } |
Prior to evaluating this texture, the 4 texture inputs col1
to col4
are evaluated, but only
one of them is needed to calculate the output value. This is inefficient if there’s a large amount
of different tiles. If this is undesirable we can use delayed evaluation to calculate only the
input we need:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <octane-oslintrin.h> shader Texture( color col1 = color(1, 0, 0), color col2 = color(0, 1, 0), color col3 = color(0, 0, 1), color col4 = color(1, 1, 1), output color c = 0) { int index = (int) floor(4 * noise("cell", u, v)); // random index if (index == 0) { c = _evaluateDelayed(col1, u, v); } if (index == 1) { c = _evaluateDelayed(col2, u, v); } if (index == 2) { c = _evaluateDelayed(col3, u, v); } if (index == 3) { c = _evaluateDelayed(col4, u, v); } } |
The flip side is that every call to _evaluateDelayed
always evaluates the input once.
There is thus no longer deduplication if there are multiple such inputs connected to the
same source.
Custom UV mapping¶
Apart from the input variable, there are two more arguments, which let you control the UV mapping of the input texture. To use this UV map change the Projection input of any node connected to this input to an OSL delayed UV projection node.
We can modify our example so the input tiles are rotated randomly at 90° intervals.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <octane-oslintrin.h> shader Texture( color col1 = color(1, 0, 0), color col2 = color(0, 1, 0), color col3 = color(0, 0, 1), color col4 = color(1, 1, 1), output color c = 0) { int rnd = (int) floor(16 * noise("cell", u, v)); // random rotation float u2 = (rnd & 1) ? u : v; float v2 = (rnd & 1) ? v : -u; u2 = (rnd & 2) ? -u2 : u2; v2 = (rnd & 2) ? -v2 : v2; // random index int index = rnd >> 2; if (index == 0) { c = _evaluateDelayed(col1, u2, v2); } if (index == 1) { c = _evaluateDelayed(col2, u2, v2); } if (index == 2) { c = _evaluateDelayed(col3, u2, v2); } if (index == 3) { c = _evaluateDelayed(col4, u2, v2); } } |
Info
To use the custom UV coordinates in another OSL node connected via a delayed input, give it
a point
input and connect a OSL delayed UV node to the corresponding input pin.
Custom 3D coordinate mapping¶
The intrinsic function _evaluateDelayedP()
is similar to evaluateDelayed()
but it overrides the value for P
. This is useful if you need to read SDFs or VDB volumes at coordinates
which are calculated in your shader.
- Evaluation is delayed until the control flow reaches this intrinsic.
- The meaning of projection nodes in the input texture changes in a similar way as projection inputs in Vectron shader trees:
P
represents the point where the SDF is being evaluated, with this intrinsic this is the passed inpos
value.- Position based projections with the coordinate space set to ‘object space’ will also use the passed in
pos
value. Projections set to ‘world space’ remain unchanged.